﻿namespace CodeProject.Podium.PowerPoint
{
    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.ServiceModel;
    using System.Text;
    using System.Windows.Forms;
    using System.Xml;
    using CodeProject.Podium.PowerPoint.Service;
    
    public class SlideShowService
    {
        ServiceHost serviceHost;
        NotificationSenderUtility notifier;
        Microsoft.Office.Interop.PowerPoint.Application application;

        public SlideShowService()
        {
            notifier = new NotificationSenderUtility();
            serviceHost = new ServiceHost(typeof(RegistrationService));
        }

        public void Initialize(Microsoft.Office.Interop.PowerPoint.Application application)
        {
            try
            {
                serviceHost.Open();
            }
            catch (TimeoutException timeoutException)
            {
                MessageBox.Show(String.Format("The service operation timed out. {0}", timeoutException.Message));
            }
            catch (CommunicationException communicationException)
            {
                MessageBox.Show(String.Format("Could not start service host. {0}", communicationException.Message));
            }

            application.SlideShowNextSlide += (window) => { PublishSlide(window); };
            application.SlideShowBegin += (window) => { PublishSlide(window); };
            application.PresentationOpen += (presentation) => { PublishPresentation(presentation); };
            application.SlideShowEnd += (window) => { PublishSlide(); };

            this.application = application;

            RegistrationService.Service = this;
        }
        
        public void Shutdown()
        {
            try
            {
                serviceHost.Close();
            }
            catch (Exception ex)
            {

            }
        }

        public void PublishPresentation(Microsoft.Office.Interop.PowerPoint.Presentation presentation)
        {
        }

        public void NextSlide()
        {
            this.application.ActivePresentation.SlideShowWindow.View.Next();
        }
        public void PreviousSlide()
        {
            this.application.ActivePresentation.SlideShowWindow.View.Next();
        }

        public void PublishSlide()
        {
            var subscribers = RegistrationService.GetSubscribers();
            notifier.SendRawNotification(subscribers, prepareRAWPayload(string.Empty), OnMessageSent);
        }

        private string CachePathFromGuid(Guid guid)
        {
            var myDocuments = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            var dir = Path.Combine(myDocuments, "PodiumCache");
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);

            string filename = dir + "\\" + guid.ToString() + ".jpg";

            return filename;
        }

        public void PublishSlide(Microsoft.Office.Interop.PowerPoint.SlideShowWindow window)
        {
            Guid guid = Guid.NewGuid();

            window.View.Slide.Copy();

            var data = Clipboard.GetDataObject();
            if (data == null) return;
            if (!data.GetDataPresent(DataFormats.Bitmap, true)) return;

            Image image = (Image)data.GetData(DataFormats.Bitmap, true);
            image.Save(CachePathFromGuid(guid), ImageFormat.Jpeg);

            var subscribers = RegistrationService.GetSubscribers();
            notifier.SendRawNotification(subscribers, prepareRAWPayload(guid.ToString()), OnMessageSent);
        }

        public byte[] GetSlide(Guid guid)
        {
            Image image = Image.FromFile(CachePathFromGuid(guid));
            using (MemoryStream stream = new MemoryStream())
            {
                image.Save(stream, ImageFormat.Jpeg);
                return stream.GetBuffer();
            }
        }

        private static byte[] prepareRAWPayload(string slide)
        {
            MemoryStream stream = new MemoryStream();
            XmlWriterSettings settings = new XmlWriterSettings() { Indent = true, Encoding = Encoding.UTF8 };
            XmlWriter writer = XmlTextWriter.Create(stream, settings);
            writer.WriteStartDocument();
            writer.WriteStartElement("SlideUpdate");
            writer.WriteStartElement("Slide");
            writer.WriteValue(slide);
            writer.WriteEndElement();
            writer.WriteStartElement("LastUpdated");
            writer.WriteValue(DateTime.Now.ToString());
            writer.WriteEndElement();
            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Close();

            byte[] payload = stream.ToArray();
            return payload;
        }

        private void OnMessageSent(CallbackArgs response)
        {
        }
    }
}
